import configData from '@/assets/config/config.json'
import widgetData from '@/assets/config/widget.json'
import highLightColor from "@/components/js/highColor";

let request; //url传入的参数
//初始化地图
export function initMap() {
    if (!dadi.util.webglreport()) {
        toastr.error('系统检测到您当前使用的浏览器WebGL功能无效');
        layer.open({
            type: 1,
            title: "当前浏览器WebGL功能无效",
            skin: "layer-dadi-dialog animation-scale-up",
            resize: false,
            area: ['600px', '200px'], //宽高
            content: '<div style="margin: 20px;"><h3>系统检测到您使用的浏览器WebGL功能无效！</h3>  <p>1、请您检查浏览器版本，安装使用最新版chrome、火狐或IE11以上浏览器！</p> <p>2、WebGL支持取决于GPU支持，请保证客户端电脑已安装最新显卡驱动程序！</p><p>3、如果上两步骤没有解决问题，说明您的电脑需要更换了！</p></div>'
        });
    }

    //记录url传入参数
    request = haoutil.system.getRequest();
    if (window.top) {//有父级
        request = $.extend(request, haoutil.system.getRequest(window.top));
    }

    haoutil.loading.show();
    haoutil.loading.hide();
    //构造地球
    let viewer = dadi.createMap({
        id: 'cesiumContainer',
        data: configData.map3d,
        serverURL: configData.serverURL,
    });

    window.viewer = viewer
    //如果有xyz传参，进行定位
    if (haoutil.isutil.isNotNull(request.x)
        && haoutil.isutil.isNotNull(request.y)) {
        // window.viewer.dadi.centerAt(request, {duration: 0, isWgs84: true});
    }

    //开场动画
    // window.viewer.dadi.openFlyAnimation();

    initWidget(window.viewer); //构造widget

    initWork(window.viewer); //项目的其他事项
}

//初始化widget相关
let lastWidgetItem

function activateWidget(item) {
    if (!window.viewer) {
        lastWidgetItem = item;
        return;
    }
    dadi.widget.activate(item);
}

function initWidget() {
    haoutil.loading.show();
    let widgetCfg = widgetData
    haoutil.loading.hide();
    //url如果有传参时的处理
    if (haoutil.isutil.isNotNull(request.widget)) {
        if (request.onlyStart) widgetCfg.widgetsAtStart = [];
        widgetCfg.widgetsAtStart.push({
            uri: request.widget,
            name: request.name || "",
            windowOptions: {
                closeBtn: !request.onlyStart,
            },
            request: request
        });
        // window.viewer.dadi.centerAtHome({duration: 0});
    }

    //初始化widget管理器
    dadi.widget.init(window.viewer, widgetCfg); //tip: 此方法有第3个参数支持定义父目录。

    if (lastWidgetItem) {
        activateWidget(lastWidgetItem);
        lastWidgetItem = null;
    }
}


//当前页面业务相关
function initWork() {
    haoutil.oneMsg('如果未出现地球，是因为地形加载失败，请刷新重新加载！', 'terrain_tip');
    //针对不同终端的优化配置
    if (haoutil.system.isPCBroswer()) {
        // Cesium 1.61以后会默认关闭反走样，对于桌面端而言还是开启得好，
        window.viewer.scene.postProcessStages.fxaa.enabled = true;

        //鼠标滚轮放大的步长参数
        window.viewer.scene.screenSpaceCameraController._zoomFactor = 2.0;

        //IE浏览器优化
        if (window.navigator.userAgent.toLowerCase().indexOf("msie") >= 0) {
            window.viewer.targetFrameRate = 20;        //限制帧率
            window.viewer.requestRenderMode = true;    //取消实时渲染
        }

    } else {
        //鼠标滚轮放大的步长参数
        window.viewer.scene.screenSpaceCameraController._zoomFactor = 5.0;

        //移动设备上禁掉以下几个选项，可以相对更加流畅
        window.viewer.requestRenderMode = true;    //取消实时渲染
        window.viewer.scene.fog.enable = false;
        window.viewer.scene.skyAtmosphere.show = false;
        window.viewer.scene.globe.showGroundAtmosphere = false;
    }

    // 禁用默认的实体双击动作。
    window.viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
    window.viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);

    //二三维切换不用动画
    if (window.viewer.sceneModePicker)
        window.viewer.sceneModePicker.viewModel.duration = 0.0;

    bindShowTilesParts();

    addCustomXyzTilePng();
    handleClickPopup();
}

function bindShowTilesParts() {
    var handler = new Cesium.ScreenSpaceEventHandler(window.viewer.scene.canvas);
    handler.setInputAction(function (event) {
        var pickedObject = window.viewer.scene.pick(event.position);
        if (pickedObject && Cesium.defined(pickedObject.primitive) &&
            pickedObject.primitive._config && pickedObject.primitive._config.scenetree) {
            var tilesParts = 'widgetsTS/tilesParts/widget.js';

            if (dadi.widget.isActivate(tilesParts)) {
                var parts = dadi.widget.getClass(tilesParts);
                if (parts.config.layerCfg == pickedObject.primitive._config)
                    return;//当前已激活,并且单击了相同模型时跳出
            }

            dadi.widget.activate({
                name: pickedObject.primitive._config.name + " 构件",
                uri: tilesParts,
                layerCfg: pickedObject.primitive._config,
                disableOther: false
            });
        }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}

// 加载离线的自定义的瓦片数据
function addCustomXyzTilePng() {
    // 创建CustomDataSource
    var xyzDataSource = new Cesium.CustomDataSource('myOfflineXYZ');
    var tilingScheme = new Cesium.GeographicTilingScheme({
        // rectangle: Cesium.Rectangle.fromDegrees(-180.0, -90.0, 180.0, 90.0),
        ellipsoid: Cesium.Ellipsoid.WGS84,
        numberOfLevelZeroTilesX: 2,
        numberOfLevelZeroTilesY: 1,
    });
    // 创建一个TileProvider来加载瓦片
    let tileProvider = new Cesium.UrlTemplateImageryProvider({
        url: `/cesium_resource/ZY_DOM_Tile_0/{z}/{x}/{y}.png`,
        tilingScheme: tilingScheme,
        // 其他必要的参数，如 availableLevels 等
        fileExtension: 'png',
    });

    // 将TileProvider添加到CustomDataSources
    xyzDataSource.imageryProvider = tileProvider;

    // 将CustomDataSource添加到Cesium Viewer
    window.viewer.dataSources.add(xyzDataSource);
    window.viewer.imageryLayers.addImageryProvider(tileProvider)
    window.viewer.camera.setView({
        destination: new Cesium.Cartesian3(-1838539.2146377198, 4745330.525285903, 3854876.9427885404),
        orientation: {
            heading: 6.242067825456471, // east, default value is 0.0 (north)
            pitch: -1.4043517637564982,    // default value (looking down)
            roll: 6.282366656507481                            // default value
        }
    });
    setTimeout(() => {
        const memoryUsageControl = new Cesium3DTilesMaximumTotalMemoryUsageControl(window.viewer.scene, 128);
        // 更新最大显存
        memoryUsageControl.maximumTotalMemoryUsage = 128;
    }, 10000);
}

let divpoint = null;

function handleClickPopup() {
    var handler = new Cesium.ScreenSpaceEventHandler(window.viewer.scene.canvas);
    handler.setInputAction(function (movement) {
        //通过鼠标当前的二维屏幕坐标获取椭球笛卡尔坐标
        var cartesian = dadi.point.getCurrentMousePosition(window.viewer.scene, movement.position);

        let pick = window.viewer.scene.pick(movement.position); // 获取 pick 拾取对象
        if (!(pick instanceof Cesium.Cesium3DTileFeature)) {
            return
        }
        const propertyNames = pick.getPropertyNames();
        const properties = {};
        propertyNames.forEach((propertyName) => {
            properties[propertyName] = pick.getProperty(propertyName);
        });
        let tileset = pick.tileset
        let name = properties.name
        tileset.style = new Cesium.Cesium3DTileStyle({
            color: {
                conditions: [
                    ["${name} === '" + name + "'", 'color("red", 1)'.replace('red', highLightColor)],
                    ['true', 'color("white")']
                ]
            },
        });

        if (Cesium.defined(pick)) {                   // 判断是否获取到了 pick
            let jsonData = pick.primitive.jsonData;
            let name = pick?.getProperty('name');
            fetch(`./file/${jsonData}.json`).then(res => res.json()).then(data => {
                let feature = data.features.find(item => {
                    if (jsonData.indexOf('POINT') != -1) {
                        return item.properties['物探点号'] === name;
                    } else {
                        return item.properties['线型码'] === name;
                    }
                })
                if (feature) {
                    let pros = feature.properties
                    let html = Object.keys(pros).map((key, i) => {
                        if (/^[a-zA-Z]*$/.test(key.replaceAll('_', ""))) {
                            return ''; // 过滤掉部分英文属性(排除_)
                        }
                        if (i % 2 === 0) {
                            return `<div><span style="display: inline-block;  width: 180px;">${key}:${pros[key] || '-'}</span>`;
                        } else {
                            return `<span style="display: inline-block; ">${key}:${pros[key] || '-'}</span></div>`;
                        }
                    }).join('')
                    divpoint && divpoint.destroy()
                    divpoint = new dadi.DivPoint(window.viewer, {
                        html: `<div style="background-color: #fff; box-shadow: 0 0 10px rgba(0,0,0,0.5); padding: 10px; color: black;">
              <span style="width:8px;height:8px;position:absolute;top:6px;right:6px;cursor:pointer;" id="closePopup">x</span>  
            ${html}
            </div>`,
                        position: cartesian,
                        anchor: [0, 0],
                        data: pros, //item为需要绑定的数据
                        // eslint-disable-next-line no-unused-vars
                        click: function (e) {//单击后的回调

                        }
                    });
                }
            })
        }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}

//UI界面相关
export function initUI() {
    haoutil.oneMsg('首次访问系统无缓存会略慢，请耐心等待！', 'load3d_tip');
}

$(document).on('click', '#closePopup', function () {
    divpoint && divpoint.destroy()
    divpoint = null;
})
class Cesium3DTilesMaximumTotalMemoryUsageControl {
    /**
     * 创建Cesium3DTiles显存管理器<br>
     *
     * <pre>
     * 该显存管理器可管理整个场景中，Cesium3DTiles使用的总显存数量。
     * 合理的使用该管理器可以有效的减少甚至避免 WebGL 由于爆显存而导致的报错。
     *
     * 值得注意的是：
     *    这里设置的最大使用显存并不是一个强制性的值，它仅仅起到一个阈值的作用。
     *    也就是当场景中 3DTiles 使用的显存超过该值时，才会触发缓存回收机制。
     *    而缓存回收后，使用的总显存并不一定会降到该值以下。
     *    比如，在当前相机视角下，3DTiles 需要 300MB 才能达到对应的显示精度，
     *    而最大使用显存设置到 200MB 时，最终使用的显存将以 Cesium 需要的显存为准，也就是 300MB。
     * <pre>
     *
     * @constructor
     * @alias Cesium3DTilesMaximumTotalMemoryUsageControl
     *
     * @param {Cesium.Scene} scene Cesium的Scene对象
     * @param {Number} maximumTotalMemoryUsage Cesium3DTiles的最大使用显存（单位MB）
     *
     */
    constructor(scene, maximumTotalMemoryUsage) {
        this._preRender = () => {
            // 计算当前使用的显存总数
            this._current3DTilesTotalMemoryUsage = 0;
            this._scene.primitives._primitives.forEach((primitive) => {
                if (primitive instanceof Cesium.Cesium3DTileset) {
                    this._current3DTilesTotalMemoryUsage +=
                        primitive.totalMemoryUsageInBytes / 1024 / 1024;
                }
            });
            // 如果显存总数超过设置的阈值
            if (this._current3DTilesTotalMemoryUsage > this.maximumTotalMemoryUsage) {
                // 手动释放上一帧未选择的所有瓦片
                this._scene.primitives._primitives.forEach((primitive) => {
                    if (primitive instanceof Cesium.Cesium3DTileset) {
                        primitive.trimLoadedTiles();
                    }
                });
            }
            // 输出内存控制数目
            // console.log(this._current3DTilesTotalMemoryUsage);

        };
        this._scene = scene;
        this.maximumTotalMemoryUsage = maximumTotalMemoryUsage;
        this._current3DTilesTotalMemoryUsage = 0;
        // tileLoad时获取新的内存占用
        this._scene.primitives._primitives.forEach((primitive) => {
            if (primitive instanceof Cesium.Cesium3DTileset) {
                primitive.tileLoad.addEventListener(this._preRender);
            }
        });
    }
    /**
     * 当前场景中Cesium3DTiles使用的显存总数(单位MB)
     *
     * @type {Number}
     * @readonly
     */
    get current3DTilesTotalMemoryUsage() {
        return this._current3DTilesTotalMemoryUsage;
    }
    /**
     * 销毁释放内存
     */
    destroy() {
        this._scene.primitives._primitives.forEach((primitive) => {
            if (primitive instanceof Cesium.Cesium3DTileset) {
                primitive.tileLoad.removeEventListener(this._preRender);
            }
        });
        Cesium.destroyObject(this);
    }
}
